﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using Telerik.Reporting.Processing;
using WCFPointOfSaleService.Class;
using WCFPointOfSaleService.Entities;
using WCFPointOfSaleService.Entities.Parameters;

namespace WCFPointOfSaleService
{
    public class OrderService : IOrderService
    {
        public ObjectResult<OrderResultList> CreateInvoice(ParamOrderWithDetail param)
        {
            ObjectResult<OrderResultList> result = new ObjectResult<OrderResultList>();
            result.data = new OrderResultList();

            bool orderIdAlreadyExist = false;
            bool orderByStockAlreadyExist = false;
            long orderIdLocalTick = 0;

            try
            {
                if (Validation.checkParameterRequired(param))
                {
                    EntityFrameworkManager.Order orderEntity;
                    EntityFrameworkManager.OrderByStock orderByStockEntity;

                    foreach (Order orderItem in param.OrderList) {

                        orderEntity = new EntityFrameworkManager.Order();
                        orderIdAlreadyExist = false;
                        orderIdLocalTick = TickManager.TickManager.GetTick(orderItem.CreationDate);

                        using (var entity = new EntityFrameworkManager.FalconSystemDBEntities())
                        {
                            var orderEntityResult = entity.Order.FirstOrDefault(x => x.CompanyID == param.CompanyID && x.UuidTransaction == orderItem.uuidTransaction && x.ClientID == orderItem.clientId && x.OrderIDLocalTick == orderIdLocalTick);

                            if (orderEntityResult != null)
                            {
                                orderIdAlreadyExist = true;
                                orderItem.orderId = orderEntityResult.OrderID;
                            }
                            else
                            {
                                orderItem.orderId = Convert.ToInt32(entity.Order_Custom_Get_NextID(param.CompanyID).FirstOrDefault());
                                entity.SaveChanges();
                            }
                        }
                        
                        using (var entity = new EntityFrameworkManager.FalconSystemDBEntities())
                        {
                            if (!orderIdAlreadyExist)
                            {
                                orderEntity.ClientID = orderItem.clientId;
                                orderEntity.CompanyID = param.CompanyID;
                                orderEntity.CreationDate = orderItem.CreationDate;
                                orderEntity.DeliveryDate = orderItem.DeliveryDate;
                                orderEntity.Discount = orderItem.discount;
                                orderEntity.IsSendInvoice = orderItem.isSendInvoice;
                                orderEntity.OrderID = orderItem.orderId;
                                orderEntity.StatusID = "PEE";
                                orderEntity.Taxes = orderItem.taxes;
                                orderEntity.Total = orderItem.total;
                                orderEntity.TotalDiscount = orderItem.totalDiscount;
                                orderEntity.TotalTaxes = orderItem.totalTaxes;
                                orderEntity.TotalToPay = orderItem.totalToPay;
                                orderEntity.TypeUserTransaction = orderItem.typeUserTransaction;
                                orderEntity.UsernameTransaction = orderItem.usernameTransaction;
                                orderEntity.UuidTransaction = orderItem.uuidTransaction;
                                orderEntity.OrderIDLocalTick = orderIdLocalTick;

                                entity.Order.Add(orderEntity);

                            }

                            foreach (OrderByStock orderByStockItem in orderItem.orderByStockList)
                            {
                                orderByStockAlreadyExist = false;

                                if (orderIdAlreadyExist)
                                {
                                    var orderByStockEntityResult = entity.OrderByStock.FirstOrDefault(x => x.CompanyID == param.CompanyID && x.OrderID == orderItem.orderId && x.StockID == orderByStockItem.stockId);
                                    
                                    if (orderByStockEntityResult != null)
                                        orderByStockAlreadyExist = true;
                                }

                                if (!orderByStockAlreadyExist)
                                {
                                    orderByStockEntity = new EntityFrameworkManager.OrderByStock();

                                    orderByStockEntity.CompanyID = param.CompanyID;
                                    orderByStockEntity.OrderID = orderItem.orderId;
                                    orderByStockEntity.Price = orderByStockItem.price;
                                    orderByStockEntity.QuantityToBuy = orderByStockItem.quantityToBuy;
                                    orderByStockEntity.StockID = orderByStockItem.stockId;

                                    entity.OrderByStock.Add(orderByStockEntity);
                                }
                            }

                            entity.SaveChanges();

                            result.data.orderResultList.Add(new OrderResult()
                            {
                                orderId = orderItem.orderId,
                                orderIdLocal = orderItem.orderIdLocal
                            });

                        }

                    }

                    try
                    {
                        var userEntities = new EntityFrameworkManager.FalconSystemDBEntities().Order.Where(x => x.TypeUserTransaction == "U" && x.StatusID == "PEE" && x.CompanyID == param.CompanyID).Distinct().ToList();

                        Entities.ObjectResult<object> resultEmailSending;

                        foreach(var userEntity in userEntities){
                            resultEmailSending = this.StartEmailSendingProcess(userEntity.CompanyID, userEntity.UsernameTransaction);
                            if (resultEmailSending.code != "00") { 
                                throw new Exception(resultEmailSending.descriptionDetail);
                            }
                        }
                        
                    }
                    catch (Exception ex) {
                        result.data.isSendingEmail = false;
                        result.data.sendingEmailDescription = ex.Message + " " + Utilities.getDescriptionDetail(ex);
                    }

                    result.data.orderResultListTotal = result.data.orderResultList.Count;
                    
                }
            }
            catch (ParameterException objex)
            {
                //devuelve el error de parametros
                result.code = objex.Code;
                result.isSuccessful = false;
                result.description = objex.Message;
            }
            catch (Exception ex)
            {
                result.code = "99";
                result.description = "No se logró registrar las facturas";
                result.descriptionDetail = Utilities.getDescriptionDetail(ex);
                result.isSuccessful = false;
            }
            return result;
        }

        public Entities.ObjectResult<object> StartEmailSendingProcess(int companyId, string username)
        {
            Entities.ObjectResult<object> result = new Entities.ObjectResult<object>();
            result.data = string.Empty;

            try
            {

                System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Start Email Sending Process");

                var emailPendingToSend = new EntityFrameworkManager.FalconSystemDBEntities().Order.Where(x => x.UsernameTransaction == username && x.TypeUserTransaction == "U" && x.StatusID == "PEE").ToList();

                System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Email To Send Stocks Pendings Entities");
                
                foreach (var orderEntity in emailPendingToSend)
                {

                    System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Send Loop for Orders");

                    var stockToSend = new EntityFrameworkManager.FalconSystemDBEntities().OrderByStock.Where(w => w.OrderID == orderEntity.OrderID && w.CompanyID == orderEntity.CompanyID).ToList();

                    //Find client
                    var clientInfoEntity = new EntityFrameworkManager.FalconSystemDBEntities().Clients.Where(x => x.ClientID == orderEntity.ClientID).FirstOrDefault();

                    if (clientInfoEntity == null)
                        throw new Exception("La información del cliente no se logró obtener. ClientId: [" + orderEntity.ClientID + "]");

                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine(System.Configuration.ConfigurationManager.AppSettings["BodyHeaderText_Order"].Replace("{Name}", clientInfoEntity.Name));
                    sb.AppendLine("");

                    DataTable dtInvoice = new DataTable();
                    dtInvoice.Columns.Add("Code");
                    dtInvoice.Columns.Add("Product");
                    dtInvoice.Columns.Add("Quantity");
                    dtInvoice.Columns.Add("Price");
                    dtInvoice.Columns.Add("Total");

                    List<EmailManager.EmailManager.CustomAttachments> listAttachment = new List<EmailManager.EmailManager.CustomAttachments>();


                    StringBuilder sbRows = new StringBuilder();
                    StringBuilder sbRowsTotal = new StringBuilder();
                    System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Generate list of stock to send");

                    sbRowsTotal.AppendLine("<tr>");
                    sbRowsTotal.AppendLine("<td class='service'>" + "Sub Total:" + "</td>");
                    sbRowsTotal.AppendLine("<td class='desc'>" + orderEntity.Total.ToString("N2", CultureInfo.InvariantCulture) + "</td>");
                    sbRowsTotal.AppendLine("</tr>");

                    sbRowsTotal.AppendLine("<tr>");
                    sbRowsTotal.AppendLine("<td class='service'>" + "Descuento [" + orderEntity.Discount + "%]:" + "</td>");
                    sbRowsTotal.AppendLine("<td class='desc'>" + orderEntity.TotalDiscount.ToString("N2", CultureInfo.InvariantCulture) + "</td>");
                    sbRowsTotal.AppendLine("</tr>");

                    sbRowsTotal.AppendLine("<tr>");
                    sbRowsTotal.AppendLine("<td class='service'>" + "Impuestos [" + orderEntity.Taxes + "%]:" + "</td>");
                    sbRowsTotal.AppendLine("<td class='desc'>" + orderEntity.TotalTaxes.ToString("N2", CultureInfo.InvariantCulture) + "</td>");
                    sbRowsTotal.AppendLine("</tr>");

                    sbRowsTotal.AppendLine("<tr>");
                    sbRowsTotal.AppendLine("<td class='service'>" + "Total:" + "</td>");
                    sbRowsTotal.AppendLine("<td class='desc'>" + orderEntity.TotalToPay.ToString("N2", CultureInfo.InvariantCulture) + "</td>");
                    sbRowsTotal.AppendLine("</tr>");

                    foreach (var stockEntity in stockToSend)
                    {
                        var stockInfoEntity = new EntityFrameworkManager.FalconSystemDBEntities().Stock.Where(x => x.CompanyID == orderEntity.CompanyID && x.StockID == stockEntity.StockID).FirstOrDefault();

                        if (stockInfoEntity == null)
                            throw new Exception("No se logró identificar el producto StockId: [" + stockEntity.StockID + "]");

                        decimal total = Convert.ToDecimal(stockEntity.Price * stockEntity.QuantityToBuy);

                        sbRows.AppendLine("<tr>");
                        sbRows.AppendLine("<td class='service'>" + stockInfoEntity.StockCode + "</td>");
                        sbRows.AppendLine("<td class='desc'>" + stockInfoEntity.Name + "</td>");
                        sbRows.AppendLine("<td class='desc'>" + Convert.ToDecimal(stockEntity.QuantityToBuy).ToString("N2", CultureInfo.InvariantCulture) + "</td>");
                        sbRows.AppendLine("<td class='desc'>" + Convert.ToDecimal(stockEntity.Price).ToString("N2", CultureInfo.InvariantCulture) + "</td>");
                        sbRows.AppendLine("<td class='desc'>" + total.ToString("N2", CultureInfo.InvariantCulture) + "</td>");
                        sbRows.AppendLine("</tr>");
                        
                        DataRow row = dtInvoice.NewRow();
                        row["Code"] = stockInfoEntity.StockCode;
                        row["Product"] = stockInfoEntity.Name;
                        row["Quantity"] = Convert.ToDecimal(stockEntity.QuantityToBuy).ToString("N2", CultureInfo.InvariantCulture);
                        row["Price"] = Convert.ToDecimal(stockEntity.Price).ToString("N2", CultureInfo.InvariantCulture);
                        row["Total"] = total.ToString("N2", CultureInfo.InvariantCulture);

                        dtInvoice.Rows.Add(row);


                        /*if (Convert.ToBoolean(System.Configuration.ConfigurationManager.AppSettings["SendStockPDFFile"]))
                        {
                            if (!String.IsNullOrEmpty(stockInfoEntity.PdfDetailUrl))
                            {
                                //Get PDf
                                StockFilesManagerService.StockFilesManagerServiceClient stockFilesManagerServiceClient = new StockFilesManagerService.StockFilesManagerServiceClient();
                                byte[] fileBytes = stockFilesManagerServiceClient.GetStockFile(stockEntity.CompanyID, stockEntity.StockID);

                                System.IO.Stream stream = new System.IO.MemoryStream(fileBytes);

                                EmailManager.EmailManager.CustomAttachments customAttachments = new EmailManager.EmailManager.CustomAttachments();
                                customAttachments.Filename = stockInfoEntity.PdfDetailUrl;
                                customAttachments.FileStream = stream;

                                listAttachment.Add(customAttachments);
                            }
                        }*/
                    }
                    //Build Invoice Html
                    sb.AppendLine(GetTemporalInvoice(orderEntity.OrderID.ToString(), sbRows.ToString(), sbRowsTotal.ToString()));


                    //Invoice PDF
                    if (orderEntity.IsSendInvoice)
                    //if (Convert.ToBoolean(System.Configuration.ConfigurationManager.AppSettings["SendInvoicePDF"]))
                    {
                        System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Generate Invoice PDF");

                        Invoice.Order rpt = new Invoice.Order();
                        StockFilesManagerService.StockFilesManagerServiceClient stockFilesManagerServiceClient = new StockFilesManagerService.StockFilesManagerServiceClient();
                        byte[] companyLogoBytes = stockFilesManagerServiceClient.GetCompanyLogo(companyId);

                        System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Get logo from StockFilesManagerServiceClient");
                        System.Drawing.Image companyLogo = byteArrayToImage(companyLogoBytes);
                        rpt.SetParameters(companyId, companyLogo, dtInvoice, System.Configuration.ConfigurationManager.AppSettings["BodyHeaderPDF_Order"].Replace("{Name}", clientInfoEntity.Name), "Factura Nº: " + orderEntity.OrderID);
                        rpt.SetParametersSubTotal(orderEntity.Total.ToString("N2", CultureInfo.InvariantCulture), orderEntity.Discount.ToString("N2", CultureInfo.InvariantCulture), orderEntity.TotalDiscount.ToString("N2", CultureInfo.InvariantCulture), orderEntity.Taxes.ToString("N2", CultureInfo.InvariantCulture), orderEntity.TotalTaxes.ToString("N2", CultureInfo.InvariantCulture), orderEntity.TotalToPay.ToString("N2", CultureInfo.InvariantCulture));

                        System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Export report to PDF");
                        MemoryStream memoryStream = ExportToPDF(rpt);

                        byte[] rptBytes = memoryStream.GetBuffer();
                        System.IO.Stream streamRpt = new System.IO.MemoryStream(rptBytes);

                        EmailManager.EmailManager.CustomAttachments customInvoiceAttachments = new EmailManager.EmailManager.CustomAttachments();
                        customInvoiceAttachments.Filename = System.Configuration.ConfigurationManager.AppSettings["InvoicePDFName_Order"].Replace("{Num}", orderEntity.OrderID.ToString()).Replace("{Name}", clientInfoEntity.Name);
                        customInvoiceAttachments.FileStream = streamRpt;

                        System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Attachment PDF");

                        listAttachment.Add(customInvoiceAttachments);
                    }

                    //Find all email by clients
                    System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Find all email from clients");
                    List<string> listAddress = new List<string>();
                    var clientsByEmailEntities = new EntityFrameworkManager.FalconSystemDBEntities().ClientsByEmail.Where(x => x.ClientID == orderEntity.ClientID).ToList();
                    foreach (var clientsByEmailEntity in clientsByEmailEntities)
                    {
                        listAddress.Add(clientsByEmailEntity.Email);
                    }

                    System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Send email to agent");
                    //Copy to Agent
                    List<string> listCC = new List<string>();
                    var userEntity = new EntityFrameworkManager.FalconSystemDBEntities().Users.Where(x => x.Username == orderEntity.UsernameTransaction && x.CompanyID == orderEntity.CompanyID).FirstOrDefault();
                    if(userEntity != null)
                        listCC.Add(userEntity.Email);

                    if (Convert.ToBoolean(System.Configuration.ConfigurationManager.AppSettings["SendCCEmailLog"])) {
                        listCC.Add(System.Configuration.ConfigurationManager.AppSettings["SendCCEmailLog_Email"]);
                    }

                    try
                    {
                        var companyEntity = new EntityFrameworkManager.FalconSystemDBEntities().Companies.Where(x => x.CompanyID == orderEntity.CompanyID).FirstOrDefault();
                        if (companyEntity == null)
                            throw new Exception("No se logró obtener la información de la compañía. companyID: [" + orderEntity.CompanyID + "]");
                        System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Sending email");
                        bool isHtmlBody = Convert.ToBoolean(System.Configuration.ConfigurationManager.AppSettings["IsHtmlBody_Order"]);
                        EmailManager.EmailManager.Send(listAddress, listCC, companyEntity.Name + "-" + System.Configuration.ConfigurationManager.AppSettings["SubjectText_Order"].Replace("{Num}", orderEntity.OrderID.ToString()), sb.ToString(), isHtmlBody, listAttachment);

                        //Update record PEE to ENF

                        using (var context = new EntityFrameworkManager.FalconSystemDBEntities())
                        {
                            var orderToUpdate = context.Order.Where(x => x.OrderID == orderEntity.OrderID && x.CompanyID == orderEntity.CompanyID).FirstOrDefault();

                            if(orderToUpdate != null){
                                orderToUpdate.StatusID = "ENF";
                            }
                            context.SaveChanges();
                        }
                        
                        System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess> Finish sending email");

                    }
                    catch (System.Net.Mail.SmtpException ex)
                    {

                        System.Diagnostics.Trace.WriteLine("StartEmailSendingProcess>SmtpException> Error - " + Utilities.getDescriptionDetail(ex));

                        GPSTrackingDBCustom.Log.WindowsServiceLog.Error(ex.Message, "EmailManager");
                        throw ex;
                    }

                }

            }
            catch (Exception ex)
            {

                //throw new Exception("No se envío los correos: Error: " + ex.Message.ToString());
                result.code = "99";
                result.isSuccessfull = false;
                result.isSuccessful = false;
                result.description = "No se envío los correos";
                result.descriptionDetail = Utilities.getDescriptionDetail(ex);

                System.Diagnostics.Trace.WriteLine(result.descriptionDetail);
            }

            return result;
        }

        private MemoryStream ExportToPDF(Telerik.Reporting.Report reportToExport)
        {
            ReportProcessor reportProcessor = new ReportProcessor();
            Telerik.Reporting.InstanceReportSource instanceReportSource = new Telerik.Reporting.InstanceReportSource();
            instanceReportSource.ReportDocument = reportToExport;
            RenderingResult result = reportProcessor.RenderReport("PDF", instanceReportSource, null);

            MemoryStream ms = new MemoryStream();
            ms.Write(result.DocumentBytes, 0, result.DocumentBytes.Length);

            return ms;

        }

        private Image byteArrayToImage(byte[] byteArrayIn)
        {
            MemoryStream ms = new MemoryStream(byteArrayIn);
            Image returnImage = Image.FromStream(ms);
            return returnImage;
        }

        private string GetTemporalInvoice(string invoiceNumber, string rows, string rowsTotal)
        {
            string html = System.IO.File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "/Invoice/Order.html");
            html = html.Replace("[INVOICENUMBER]", "Factura Nº: " + invoiceNumber);
            html = html.Replace("[TR_ROWS]", rows);
            html = html.Replace("[TR_ROWS_TOTAL]", rowsTotal);

            return html;
        }

    }
}
